﻿/**
 * 8051虚拟机的实现部分
 *
 * 创建时间：2022年5月13日
 * 作者：李述铜
 * 联系邮箱: 527676163@qq.com
 */
#ifndef SIMU8051_H
#define SIMU8051_H

#include <stdint.h>

#define INT_TIMER0_ENTRY	0x0B

#define SFR_ACC				0xE0
#define SFR_SP				0x81
#define SFR_B				0xF0
#define SFR_DPH				0x83
#define SFR_DPL				0x82
#define SFR_PSW				0xD0
#define SFR_PSW_CY			(0xD0 + 7)
#define SFR_PSW_AC			(0xD0 + 6)
#define SFR_PSW_OV			(0xD0 + 2)
#define SFR_PSW_P			(0xD0 + 0)

#define SFR_SBUF			0x99
#define SFR_SCON			0x98
#define SFR_SCON_TI			(0x98 + 1)
#define SFR_SCON_RI			(0x98 + 0)

#define SFR_TCON			0x88
#define	SFR_TCON_TR0		(0x88 + 4)
#define SFR_TCON_TF0		(0x88 + 5)

#define SFR_TMOD			0x89
#define SFR_TH0				0x8C
#define SFR_TL0				0x8A

#define SFR_IE				0xA8


#define MEM_BIT_SFR_START		0x80
#define MEM_BIT_IRAM_START		0x20

#define MEM_CODE_SIZE			65536
#define MEM_IRAM_SIZE			128
#define MEM_SFR_SIZE			128
#define MEM_XRAM_SIZE			65536

typedef enum _mem_type_t {
	MEM_TYPE_IRAM,
	MEM_TYPE_XRAM,
	MEM_TYPE_CODE,
	MEM_TYPE_BIT,
	MEM_TYPE_SFR,
}mem_type_t;

typedef struct _memory_t {
	uint8_t* code;
	uint8_t iram[MEM_IRAM_SIZE];
	uint8_t sfr[MEM_SFR_SIZE];
	uint8_t xram[MEM_XRAM_SIZE];
}memory_t;

typedef struct _simu8051_t {
	memory_t mem;
	uint16_t pc;
	uint32_t cycles;

	int in_int;
}simu8051_t;

struct _instr_info_t;
typedef struct _instr_t {
	uint8_t opcode;
	uint8_t op0;
	uint8_t op1;
	const struct _instr_info_t* info;
}instr_t;

typedef enum _op_type_t {
	OTYPE_NONE,
	OTYPE_Rn,
	OTYPE_IMM8,
	OTYPE_ACC,
	OTYPE_DIRECT,
	OTYPE_DPTR,
	OTYPE_IMM16,
	OTYPE_IND_R0_1,
	OTYPE_C,
	OTYPE_BIT,
	OTYPE_IND_A_PC,
	OTYPE_IND_A_DPTR,
	OTYPE_IND_DPTR,
	OTYPE_IND_SP,
	OTYPE_B,
}op_type_t;

typedef struct _instr_info_t {
	uint8_t bytes;
	uint8_t cycles;
	op_type_t op0_mode;
	op_type_t op1_mode;
	void (*exec) (instr_t* instr);
	const char* disa;
}instr_info_t;

uint8_t simu8051_read(mem_type_t type, uint16_t addr);
void simu8051_write(mem_type_t type, uint16_t addr, uint8_t data);

void simu8051_reset(void);
void simu8051_init(void);

void simu8051_load(uint8_t* code);
uint16_t simu8051_pc(void);
uint32_t simu8051_cycle(void);
void simu8051_fetch_instr(instr_t* instr);
void simu8051_exec(instr_t* instr);

void simu8051_run(uint16_t stop_addr, uint32_t stop_cyle);

void simu8051_uart_write(char c);
int simu8051_uart_rx_rdy(void);
char simu8051_uart_read(void);

#endif // !SIMU8051_H
